<?php

namespace addons\fastworker\library\command;

use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use addons\fastworker\library\Server as WorkerServer;
use Workerman\Worker;

/**
 * Fastworker Server 命令行类
 */
class Server extends Command
{

    protected $config;

    public function configure()
    {
        $this->setName('fastworker:server')
            ->addArgument('action', Argument::OPTIONAL, "start|stop|restart|reload|status|connections", 'start')
            ->addOption('host', 'host', Option::VALUE_OPTIONAL, 'the host of workerman server.', null)
            ->addOption('port', 'port', Option::VALUE_OPTIONAL, 'the port of workerman server.', null)
            ->addOption('name', 'name', Option::VALUE_OPTIONAL, 'the name of workerman instance.', null)
            ->addOption('count', 'count', Option::VALUE_OPTIONAL, 'the number of workerman processes', null)
            ->addOption('protocol', 'protocol', Option::VALUE_OPTIONAL, 'the protocol of workerman server', null)
            ->addOption('class', 'class', Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'the worker class for workerman server', null)
            ->addOption('daemon', 'daemon', Option::VALUE_NONE, 'Run the workerman server in daemon mode.')
            ->setDescription('Fastworker Server : Run workerman server');

    }

    public function execute(Input $input, Output $output)
    {
        $action = $input->getArgument('action');

        if (DIRECTORY_SEPARATOR !== '\\') {
            if (!in_array($action, ['start', 'stop', 'reload', 'restart', 'status', 'connections'])) {
                $output->writeln("<error>Invalid argument action:{$action}, Expected start|stop|restart|reload|status|connections .</error>");
                return false;
            }

            global $argv;
            array_shift($argv);
            array_shift($argv);
            array_unshift($argv, 'think', $action);
        } elseif ('start' != $action) {
            $output->writeln("<error>Not Support action:{$action} on Windows.</error>");
            return false;
        }

        $port =  $this->getOption('port',2345);
        $this->config = [
            'protocol'       => $this->getOption('protocol','websocket'), // 协议 支持 tcp udp unix http websocket text
            'host'           => $this->getOption('host','0.0.0.0'),
            'port'           => $port,


            'context'        => [], // socket 上下文选项

            'ssl'            => false,

            'name'           => $this->getOption('name','fastworker-'.$port),
            'count'          => $this->getOption('count',1),
            'daemonize'      => $this->input->hasOption('daemon'),
            'pidFile'        => ROOT_PATH . 'runtime/worker.pid'.$port,

            // 支持事件回调
            'onWorkerStart'  => function ($worker) {

            },
            'onWorkerReload' => function ($worker) {

            },
            'onConnect'      => function ($connection) {

            },
            'onMessage'      => function ($connection, $data) {
                $connection->send('receive success');
            },
            'onClose'        => function ($connection) {

            },
            'onError'        => function ($connection, $code, $msg) {
                echo "error [ $code ] $msg\n";
            },
        ];

        if ('start' == $action) {
            $output->writeln('Starting Workerman server...');
        }

        // 设置回调类
        $workerClass =  $this->getOption('class',[]);
        if ($workerClass) {
            foreach ($workerClass as $server) {
                $this->startServer($server);
            }

            Worker::runAll();
            return;
        }

        $socket   = $this->config['protocol'] . '://' . $this->config['host'] . ':' . $this->config['port'];
        unset($this->config['host'], $this->config['port'], $this->config['protocol']);


        $worker = new Worker($socket, $this->config['context']);
        unset($this->config['context']);


        if ($this->config['ssl']) {
            $this->config['transport'] = 'ssl';
            unset($this->config['ssl']);
        }
        unset($this->config['ssl']);

        // 设置服务器参数
        foreach ($this->config as $name => $val) {
            if (in_array($name, ['stdoutFile', 'daemonize', 'pidFile', 'logFile'])) {
                Worker::${$name} = $val;
            } else {
                $worker->$name = $val;
            }
        }

        Worker::runAll();
    }

    protected function startServer(string $class)
    {
        if (class_exists($class)) {
            $worker = new $class;
            if (!$worker instanceof WorkerServer) {
                $this->output->writeln("<error>Worker Server Class Must Extends \\addons\\fastworker\\library\\Server</error>");
            }
        } else {
            $this->output->writeln("<error>Worker Server Class Not Exists : {$class}</error>");
        }
    }

    protected function getOption($name,$default){
        if ($this->input->hasOption($name)) {
            return $this->input->getOption($name);
        }
        return $default;
    }
}
